package com.lead.security.encryption.rsa;

import android.util.Base64;

import com.lead.security.interfaces.Security;
import com.lead.security.utils.HexUtil;

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;


/**
 *提供公钥加密
 *
 */
public class RSAManager implements Security {

    private static final String TAG = RSAManager.class.getSimpleName();
    private final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXQXYOY6qwHuz48iN0aNosm" +
            "h89\r+33nTYvtI96OtzSwdxqoirOs/j0iPyTAV6N/iXbNWSpQYfuhDPohKsdEjvTOlxCj\rxeyxdu0Q9VYS3pdu3" +
            "aGgAPr3SSPvqAZF0GVFiMG8MUooh5rtou0IsLg8NYLvPeH+\rkSWqZxMM380xKHMkYQIDAQAB\r";

    private String ALGORITHM_RSA = "RSA";
    private String ALGORITHM_RSA_NONE = "RSA/NONE/NoPadding";

    private final String CHARSET_UTF8 =  "utf-8";

    private PublicKey pk = null;
    /**
     *rsa加密数据最大限制
     */
    private final int DATA_BLOCK = 117;
    private static final RSAManager rsaManager = new RSAManager();


    public RSAManager(){}
    public static RSAManager getInstance() {
        return rsaManager;
    }

    public void init() throws Exception{
        //生成公钥
        X509EncodedKeySpec x509 = new X509EncodedKeySpec(Base64.decode(publicKey, Base64.NO_PADDING));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
        pk = keyFactory.generatePublic(x509);
    }

    @Override
    public byte[] decrypt(byte[] input) {

        return new byte[0];
    }

    @Override
    public byte[] encrypt(byte[] input) {
        return new byte[0];
    }

    @Override
    public String decrypt(String input) {
        return null;
    }

    @Override
    public String encrypt(String input) throws Exception {

        if(input == null || input.isEmpty()){
            return "";
        }
        String encStr = "";

        Cipher cipher = Cipher.getInstance(ALGORITHM_RSA_NONE);
        cipher.init(Cipher.ENCRYPT_MODE,pk);
        byte[] encByte = enc(cipher,input.getBytes(CHARSET_UTF8));
        encStr = HexUtil.toHex(encByte);
        return encStr;
    }


    /**
     * 当加密数据超过117个字节，进行分块加密
     * @param cip
     * @param source
     * @return
     */
    private byte[] enc(Cipher cip, byte[] source) throws Exception{

        ByteArrayOutputStream baos = null;
        byte[] encByte = null;

        baos = new ByteArrayOutputStream();
        int tmp = source.length;
        if(tmp <=DATA_BLOCK){
            return cip.doFinal(source);
        }
        if(tmp%DATA_BLOCK == 0){
            tmp = tmp/DATA_BLOCK;
            for (int i = 0; i <tmp; i++) {
                baos.write(cip.doFinal(source, i*DATA_BLOCK,DATA_BLOCK));
            }
        }else{
            tmp = tmp/DATA_BLOCK;
            for (int i = 0; i < tmp; i++) {
                baos.write(cip.doFinal(source, i*DATA_BLOCK,DATA_BLOCK));
            }
            tmp = source.length;
            baos.write(cip.doFinal(source, tmp-tmp%DATA_BLOCK,tmp%DATA_BLOCK));
        }
        baos.flush();
        encByte = baos.toByteArray();


        if(baos != null){
            baos.close();
            baos = null;
        }
//        try {
//            baos = new ByteArrayOutputStream();
//            int tmp = source.length;
//            if(tmp <=DATA_BLOCK){
//                return cip.doFinal(source);
//            }
//            if(tmp%DATA_BLOCK == 0){
//                tmp = tmp/DATA_BLOCK;
//                for (int i = 0; i <tmp; i++) {
//                    baos.write(cip.doFinal(source, i*DATA_BLOCK,DATA_BLOCK));
//                }
//            }else{
//                tmp = tmp/DATA_BLOCK;
//                for (int i = 0; i < tmp; i++) {
//                    baos.write(cip.doFinal(source, i*DATA_BLOCK,DATA_BLOCK));
//                }
//                tmp = source.length;
//                baos.write(cip.doFinal(source, tmp-tmp%DATA_BLOCK,tmp%DATA_BLOCK));
//            }
//            baos.flush();
//            encByte = baos.toByteArray();
//        } catch (IllegalBlockSizeException e) {
//            LogBus.e(TAG,"IllegalBlockSizeException",e);
//        } catch (BadPaddingException e) {
//            LogBus.e(TAG,"BadPaddingException",e);
//        } catch (IOException e) {
//            LogBus.e(TAG,"IOException",e);
//        }finally {
//            try {
//                if(baos != null){
//                    baos.close();
//                    baos = null;
//                }
//            } catch (IOException e) {
//                LogBus.e(TAG,"IOException",e);
//            }
//        }
        return encByte;
    }



}
